#ifndef OWL_EYE_WAVELET_H
#define OWL_EYE_WAVELET_H

#include "axle/core.h"
#include <algorithm>

#include "axle/img/image_ip.hpp"

namespace oe {
template<typename T>
class Wavelet {
public:
  typedef typename T::PixelType PixelType;
  Wavelet(T &img) : img_(img) {
    int n = std::max(img.width(), img.height());
    array_ = new PixelType[n];
    temp_img_.Allocate(img.height(), img.width());
    s_sqrt_2 = 1.f / sqrtf(2.f);
  }
  ~Wavelet() {
    delete[] array_;    
  }  
  void Decompose() {
    norm_factor_ = 1.f / sqrtf(img_.width());
    for (int i = 0; i < img_.height(); ++i) {
      DecomposeArray(img_[i], img_.width());
    }
    
    // transpose
    img::Transpose(img_, temp_img_);
    norm_factor_ = 1.f / sqrtf(temp_img_.width());
    for (int i = 0; i < temp_img_.height(); ++i) {
      DecomposeArray(temp_img_[i], temp_img_.width());
    }
    img::Transpose(temp_img_, img_);
  }
  void Restore() {
  }
  void GetMLargests(int m, int *sig, int *avg) {

  }
private:  
  void DecomposeArray(PixelType *A, int n) {    
    // row <- row / sqrt(h)    
    for (int i = 0; i < n; ++i) {
      //A[i] *= norm_factor_;
    }
    while (n > 1) {
      int h = n >> 1;
      for (int i = 0; i < h; ++i) {
        int idx = i << 1;
        array_[i] = (A[idx] + A[idx + 1]) * s_sqrt_2;
        array_[h + i] = (A[idx] - A[idx + 1]) * s_sqrt_2;
      }
      memcpy(A, array_, n * sizeof(PixelType));
      n = h;      
    }
  }
private:
  T &img_;
  PixelType *array_;
  T temp_img_;
  float norm_factor_;
  static float s_sqrt_2;
};

template<typename T> float Wavelet<T>::s_sqrt_2 = sqrtf(2.f);

} // oe

#endif // OWL_EYE_WAVELET_H

